package com.ideal.gpt.ability.docqa.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.ideal.gpt.GptJobConfig;
import com.ideal.gpt.ability.docqa.QaFiller;
import com.ideal.gpt.ability.docqa.caller.DocQaCaller;
import com.ideal.gpt.ability.docqa.splitter.ResponseSplitter;
import com.ideal.gpt.ability.docqa.splitter.ResponseSplitter.SplitResult;
import com.ideal.gpt.app.docqajob.QaParseJob.QuestionType;
import com.lzwork.gpt.utility.caller.GptCallResult;
import com.lzwork.utility.dictionary.SetDictionary;
import com.lzwork.utility.logger.LOGGER;
import com.lzwork.utility.str.StrUtility;
import com.lzwork.web.BaseController;
import com.lzwork.web.WebResultCode;

/**
 * @author LiZheng
 * @date 2023年12月7日 上午10:33:03
 */

@Controller
@RequestMapping(value = "/docqa/*")
public class DocQaController extends BaseController
{
	protected boolean apiLog = false;

	@PostMapping(value = "/chat", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public JSONObject chat(@RequestBody Map<?, ?> map)
	{
		JSONObject result = new JSONObject();
		String content = getMapStr(map, "content");
		boolean dolog = getMapBool(map, "dolog");
		boolean dosplit = getMapBool(map, "dosplit");

		String url = getMapStr(map, "url");
		if (!StrUtility.stringValid(url))
			url = GptJobConfig.url();

		DocQaCaller caller = new DocQaCaller(url);

		try
		{
			if (apiLog)
				LOGGER.log(LOGGER.APP, "Api call chat: " + content);

			GptCallResult cr;
			if (dosplit)
			{
				List<String> input = new ArrayList<>();
				String[] parts = content.split("\n");
				for (String part : parts)
				{
					String str = part.replace("\r", "");
					str = str.trim();
					if (StrUtility.stringValid(str))
						input.add(part);
				}
				cr = caller.callChat(input, "chat from api", dolog);
			} else
				cr = caller.callChat(content, "chat from api", dolog);

			result.put("content", cr.getResponse());
			result.put("cost", cr.getGpuCost());
		} catch (Exception e)
		{
			e.printStackTrace();
			String err = LOGGER.exceptionInfo(e);
			return errReturn(err);
		}

		return result;
	}

	ParseQaCall parseQaCall = new ParseQaCall("{{input}}", "{{num}}", "{{answer}}");

	@PostMapping(value = "/parse", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public JSONObject parse(@RequestBody Map<?, ?> map)
	{
		String content = getMapStr(map, "content");
		int num = getMapInt(map, "num", 3);
		int type = getMapInt(map, "type", 1);
		boolean dolog = getMapBool(map, "dolog");
		boolean noAnswer = getMapBool(map, "noAnswer");

		int callType = getMapInt(map, "callType", -1);

		if (!StrUtility.stringValid(content))
			return errReturn("文本信息不能为空");
		if (num < 1)
			return errReturn("出题数量必须大于0");

		boolean fixed = getMapBool(map, "fixed", false);
		if (fixed)
			callType = 4;
		else if (callType < 0)
			callType = GptJobConfig.getIntProp("calltype", 1);

		QuestionType qType = QuestionType.parseBit(type);
		if (qType == QuestionType.Unknown)
			return WebResultCode.PARAMETER_INVALID.toErrJobj("Unknown titleType: " + type);

		return parseQaCall.parseQa(callType, content, qType, num, noAnswer, dolog);
	}

	public static JSONObject parseQa(String url, int type, String content, boolean noAnswer, int num, boolean dolog)
	{
		JSONObject result = new JSONObject();
		DocQaCaller caller = new DocQaCaller(url);

		try
		{
			int typeParam = type;

			switch (type)
			{
			case 100: // check key only
				typeParam = 14;
				break;
			case 1: // 简答
				break;
			case 2: // 单选
				break;
			case 3: // 判断
				break;
			case 4: // 多选
				typeParam = 5;
				break;
			case 5: // 填空
				typeParam = 14;
			default:
				break;
			}

			if (typeParam < 10 && noAnswer)
				typeParam += 20;

			GptCallResult cr = caller.callParse(content, typeParam, num, "Api call parse, type:" + typeParam, dolog);

			if (type == 100)
			{
				ResponseSplitter splitter = new ResponseSplitter(1, dolog);

				SetDictionary<String> parts = splitter.splitKeywords(cr.getResponse());
				result.put("content", parts.toString());

			} else if (type == 5)
			{
				ResponseSplitter splitter = new ResponseSplitter(1, dolog);
				SplitResult qasp = splitter.splitResponse(cr.getResponse(), typeParam);

				if (qasp.isEmpty())
					result.put("content", cr.getResponse());
				else
					result.put("content", QaFiller.resultToString(qasp.target(), noAnswer));

			} else
				result.put("content", cr.getResponse());

			result.put("cost", cr.getGpuCost());
		} catch (Exception e)
		{
			e.printStackTrace();
			String err = LOGGER.exceptionInfo(e);
			return WebResultCode.PARAMETER_INVALID.toErrJobj(err);
		}

		return WebResultCode.SUCCESS.toDataJobj(result);
	}
}
